package cn.rocksolid.sport.common.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import cn.rocksolid.sport.common.error.RSE;
import cn.rocksolid.sport.common.error.RockSolidException;

public class XmlUtils {

  private static final String REQ_ROOT_ELEMENT_NAME = "xml";
  private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
  private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();

  private XmlUtils() {
  }

  public static Map<String, String> flatXmlToMap(final byte[] xmlSource) {
    try (InputStream stream = new ByteArrayInputStream(xmlSource)) {
      DocumentBuilder documentBuilder = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder();
      Document doc = documentBuilder.parse(stream);
      doc.getDocumentElement().normalize();
      NodeList nodeList = doc.getDocumentElement().getChildNodes();
      Map<String, String> result = new HashMap<>();
      for (int idx = 0; idx < nodeList.getLength(); ++idx) {
        Node node = nodeList.item(idx);
        if (node.getNodeType() == Node.ELEMENT_NODE) {
          result.put(((Element) node).getNodeName(), ((Element) node).getTextContent());
        }
      }
      return result;
    } catch (Exception exp) {
      throw new RockSolidException(RSE.XML_TRANSFORM_ERR);
    }
  }

  public static byte[] mapToFlatXml(final Map<String, String> data) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
      DocumentBuilder documentBuilder = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder();
      Document document = documentBuilder.newDocument();
      Element root = document.createElement(REQ_ROOT_ELEMENT_NAME);
      document.appendChild(root);
      for (Entry<String, String> entry : data.entrySet()) {
        Element filed = document.createElement(entry.getKey());
        filed.appendChild(document.createTextNode(StringUtils.defaultString(entry.getValue()).trim()));
        root.appendChild(filed);
      }
      Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
      transformer.transform(new DOMSource(document), new StreamResult(baos));
      return baos.toByteArray();
    } catch (Exception exp) {
      throw new RockSolidException(RSE.XML_TRANSFORM_ERR);
    }
  }
}
